<!DOCTYPE HTML>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  
  <title>Spring-AOP揭秘 › 但行好事，莫问前程</title>
  <meta name="author" content="fengbo">
  
  <meta name="description" content="不想当架构师的程序员不是好厨师 ，不认为PHP是世界上最好的编程语言的Python开发者不是一个好的Javaer。">
  
  
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  <meta property="og:title" content="Spring-AOP揭秘">
  <meta property="og:site_name" content="但行好事，莫问前程">

  
    <meta property="og:image" content="undefined">
  

  <link href="/favicon.png" rel="icon">
  <link rel="alternate" href="/atom.xml" title="但行好事，莫问前程" type="application/atom+xml">
  <link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">
  <!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
  

</head>
</html>

<body>
  <header id="header"><div class="meta inner">
  <h1><a href="/">但行好事，莫问前程</a></h1>
  <h2><a href="/">CV工程师，了解面向Google编程的基本原理，有三年使用Google经验，在通往程序员的道路上艰难的爬行着。</a></h2>
  <nav id="main-nav">
    <ul>
      
      <li><a href="/">Home</a></li>
      
      <li><a href="/archives">Archives</a></li>
      
      <li><a href="/atom.xml">RSS</a></li>
      
    </ul>
    <div class="clearfix"></div>
  </nav>
</div>
<div class="clearfix"></div>
</header>
  <div id="content" class="inner">
    <div id="main-col" class="alignleft"><div id="wrapper"><article class="post">
  <div class="post-content">
    <header>
      
  
    <h1 class="title">Spring-AOP揭秘</h1>
  

      
        <time datetime="2018-06-23T02:25:17.000Z">2018-06-23</time>
      
    </header>
    <div class="entry">
      
        <p>AOP（面向切面编程）是面向对象编程模式的一个补足，负责将系统中的日志记录、安全检查、事物管理等无法通过OOP模块化的重复代码模块化，避免不必要的代码散落。而Spring AOP采用Java作为AOP的实现语言（AOL），较之想AspectJ那种语言扩展型的AOP实现，SpringAOP可以更快捷的融入开发，学习曲线相对平滑得多。<br><a id="more"></a></p>
<h2 id="AOP基础概念"><a href="#AOP基础概念" class="headerlink" title="AOP基础概念"></a>AOP基础概念</h2><ul>
<li>在系统运行前，AOP的功能模块都需要织入到OOP的功能模块中。进行这种织入过程，需要知道在系统的哪些执行点上进行织入操作，这些将要在其之上进行织入操作的系统执行点称之为Joinpoint。下面列举了常见的Joinpoint类型（Spring AOP只支持<b>方法执行</b>类型的Joinpoint）：<ol>
<li>方法调用：当某个方法被调用的时候所处的程序执行点。</li>
<li>方法执行：不同于方法调用是在调用对象的执行点，方法执行是在被调用到的方法执行的时点。对于同一对象，方法调用先于方法执行。</li>
<li>构造方法调用：程序执行过程中对某个对象调用其构造方法进行初始化的时点。</li>
<li>字段设置：对象的某个属性通过setter方法被设置或者直接被设置的时点。</li>
<li>字段获取：相对于字段设置型的Joinpoint，字段获取型的Joinpoint，对应是某个对象相应属性被访问的时点。</li>
<li>异常处理执行：该类型的Joinpoint对应程序执行中，在某些异常类型抛出后，对应的异常处理逻辑执行的时点。</li>
<li>类初始化：类中某些静态类型或静态块的初始化时点。</li>
</ol>
</li>
<li>Pointcut：Joinpoint的表述方式。将横切逻辑织入当前系统的过程中，需要参照Pointcut规定的Joinpoint信息，才能知道应该往系统的哪些Joinpoint上织入横切逻辑。</li>
<li>Advice：单一横切关注点逻辑的载体，<b>代表将会织入到Joinpoint的横切逻辑。</b></li>
<li>Aspect：对系统中的横切关注点逻辑进行模块化封装的AOP概念实体。通常情况下，Aspect可以包含多个Pointcut已经相关的Advice定义。</li>
<li>织入器：负责将横切逻辑织入到目标对象。</li>
<li>目标对象：指符合Pointcut所指定的条件，将在织入过程中被织入横切逻辑的对象。</li>
</ul>
<h2 id="Java平台的AOP实现机制"><a href="#Java平台的AOP实现机制" class="headerlink" title="Java平台的AOP实现机制"></a>Java平台的AOP实现机制</h2><ul>
<li>动态代理（Spring默认使用）：JDK1.3之后引入了一种称之为动态代理的机制。使用该机制，我们可以为指定的接口在系统运行期间动态地生成代理对象。<ol>
<li>缺点：被代理的类必须实现了相应的接口，如果某个类没有实现任何接口就没有办法使用该机制。</li>
</ol>
</li>
<li>CGLIB动态字节码生成：如果Spring AOP发现目标对象没有实现任何接口，就会尝试使用该CGLIB的开源的动态字节码生成类库，为目标对象动态的构建子类的字节码的class文件。<ol>
<li>原理：对目标对象进行继承扩展，为其生成相应的子类，而子类可以通过覆写来扩展父类的行为，只要将横切逻辑实现放到子类中，然后让系统使用扩展后的目标对象的子类，就可以达到与代理模式相同的效果了。</li>
<li>缺点：无法对私有方法和final方法进行覆写。</li>
</ol>
</li>
<li>Java代码生成：根据部署描述符文件提供的织入信息，为相应的功能模块类生成对应的Java代码，然后通过部署工具或部署接口编译Java代码生成相应的Java类。</li>
<li>自定义类加载器：通过读取外部文件规定的织入规则和必要信息，在加载class文件期间就可以将横切逻辑添加到系统模块类的现有逻辑中，然后将改动后的class交给Java虚拟机运行。</li>
<li>AOL扩展：AspectJ使用的方式，在这种方式中，AOP的各种概念在AOL中大都有一一对应的实体。</li>
</ul>
<h2 id="Spring-AOP实现机制"><a href="#Spring-AOP实现机制" class="headerlink" title="Spring AOP实现机制"></a>Spring AOP实现机制</h2><h3 id="织入器-org-springframework-aop-framework-ProxyFactory"><a href="#织入器-org-springframework-aop-framework-ProxyFactory" class="headerlink" title="织入器 - org.springframework.aop.framework.ProxyFactory"></a>织入器 - org.springframework.aop.framework.ProxyFactory</h3><ol>
<li>ProxyFactory的父类ProxyCreatorSupport的有参构造方法中会接收一个AopProxyFactory作为创建AopProxy的工厂类。如果使用无参的构造方法，在构造方法中会创建一个DefaultAopProxyFactory实例，当然也可以通过setAopProxyFactory方法替换该实例。</li>
<li>AopProxyFactory会根据传入的AdvisedSupport实例提供的相关信息，来决定生成什么类型的AopProxy。</li>
<li>AdvisedSupport是一个生成代理对象所需要的信息的载体。该类继承了ProxyConfig类并实现了Advised接口。其中，ProxyConfig记录生成代理对象所需要的控制信息；Advised记录生成代理对象所需要的必要信息，如相关目标类、Advice、Advisor等。</li>
</ol>
<h3 id="Aspect-org-springframework-aop-Advisor"><a href="#Aspect-org-springframework-aop-Advisor" class="headerlink" title="Aspect - org.springframework.aop.Advisor"></a>Aspect - org.springframework.aop.Advisor</h3><p>Advisor是一种特殊的Aspect，通常只持有一个Pointcut和一个Advice。</p>
<h3 id="Advice-org-aopalliance-aop-Advice"><a href="#Advice-org-aopalliance-aop-Advice" class="headerlink" title="Advice - org.aopalliance.aop.Advice"></a>Advice - org.aopalliance.aop.Advice</h3><ul>
<li>per-class类型的Advice：该类型的Advice的实例可以在目标对象类的所有实例间共享。这种类型的Advice通常只提供方法拦截功能，不会为目标对象类保存任何状态或者添加任何属性。</li>
<li>per-instance类型的Advice：不会在目标类所有对象实例之间共享，而是会为不同的实例对象保存它们各自的状态以及相关逻辑。外在表现为可以为目标对象添加属性。</li>
</ul>
<h3 id="Pointcut-org-springframework-aop-Pointcut"><a href="#Pointcut-org-springframework-aop-Pointcut" class="headerlink" title="Pointcut - org.springframework.aop.Pointcut"></a>Pointcut - org.springframework.aop.Pointcut</h3><ol>
<li>Pointcut持有ClassFilter和MethodMatcher的引用，ClassFilter和MethodMatcher则分别用于匹配将被织入操作的对象以及相应的方法。</li>
<li>根据MethodMatcher的isRuntime的返回值的不同，分为静态类型匹配和动态类型匹配。<ol>
<li>返回false表示不会考虑具体Jointpoint的方法参数，这种类型的MethodMatcher称为StaticMethodMatcher。因为不用每次检查参数，那么对同类型的方法匹配结果，就可以在框架内缓存以提高性能。</li>
<li>当isRuntime返回true时，表明该MethodMatcher将会每次都对调用的参数进行匹配检查，这种类型的MethodMatcher称之为DynamicMethodMatcher。因为每次都要对方法参数进行检查，无法对匹配结果进行缓存。</li>
</ol>
</li>
<li>在MethodMatcher的基础上，Pointcut分为两类，即StaticMethodMatcherPointcut和DynamicMethodMatcherPointcut。</li>
</ol>
<h2 id="AOP在Spring内部的应用"><a href="#AOP在Spring内部的应用" class="headerlink" title="AOP在Spring内部的应用"></a>AOP在Spring内部的应用</h2><ol>
<li>全局异常处理：对于RuntimeException，通常就是记录日志、通知相应人员、给用户一个统一的信息等。所以，这些相同的逻辑实现可以归并与一处进行处理。</li>
<li>使用拦截器获取Spring Security框架进行安全检查、Spring缓存机制、Spring事物等。</li>
</ol>

      
    </div>
      
      <footer>
        
        
  
  <div class="tags">
    <a href="/tags/Spring基础/">Spring基础</a>
  </div>

        
  <div class="addthis addthis_toolbox addthis_default_style">
    
      <a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>
    
    
      <a class="addthis_button_tweet"></a>
    
    
      <a class="addthis_button_google_plusone" g:plusone:size="medium"></a>
    
    
      <a class="addthis_button_pinterest_pinit" pi:pinit:layout="horizontal"></a>
    
    <a class="addthis_counter addthis_pill_style"></a>
  </div>
  <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js"></script>

      
      <div class="clearfix"></div>
      </footer>
  </div>
</article>

<!-- 来必力City版安装代码 -->
<!-- <div id="lv-container" data-id="city" data-uid="MTAyMC8yOTQ5MS82MDU5">
<script type="text/javascript">
   (function(d, s) {
       var j, e = d.getElementsByTagName(s)[0];

       if (typeof LivereTower === 'function') { return; }

       j = d.createElement(s);
       j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
       j.async = true;

       e.parentNode.insertBefore(j, e);
   })(document, 'script');
</script>
<noscript>为正常使用来必力评论功能请激活JavaScript</noscript>
</div> -->
<!-- City版安装代码已完成 -->

</div></div>
    <aside id="sidebar" class="alignright">
  
<div class="widget tagcloud">
  <h3 class="title">文章分类</h3>
  <div class="entry">
    <a href="/tags/JavaWeb/" style="font-size: 17.14px;">JavaWeb</a> <a href="/tags/Java基础/" style="font-size: 15.71px;">Java基础</a> <a href="/tags/Java高级特性/" style="font-size: 15.71px;">Java高级特性</a> <a href="/tags/Python/" style="font-size: 10px;">Python</a> <a href="/tags/Spring基础/" style="font-size: 14.29px;">Spring基础</a> <a href="/tags/WebRTC/" style="font-size: 10px;">WebRTC</a> <a href="/tags/其它/" style="font-size: 20px;">其它</a> <a href="/tags/分布式/" style="font-size: 11.43px;">分布式</a> <a href="/tags/硬件/" style="font-size: 12.86px;">硬件</a> <a href="/tags/计算机基础/" style="font-size: 18.57px;">计算机基础</a> <a href="/tags/设计模式/" style="font-size: 17.14px;">设计模式</a>
  </div>
</div>



    <div class="widget tagcloud">
    <h3 class="title">电子书</h3>
    <ul class="entry">
      <li class='link'><a href='http://www.duokan.com/' target="_blank">多看阅读</a>&nbsp;&nbsp;<a href='https://read.douban.com/' target="_blank">豆瓣阅读</a>&nbsp;&nbsp;<a href='http://e.dangdang.com/' target="_blank">当当阅读</a></li>
      <li class='link'><a href='http://www.ituring.com.cn/' target="_blank">图灵社区</a>&nbsp;&nbsp;<a href='https://www.epubit.com/' target="_blank">异步社区</a>&nbsp;&nbsp;<a href='https://www.geekbang.org/' target="_blank">极客空间</a></li>
    </ul>
  </div>


  
  <div class="widget tag">
    <h3 class="title">友情链接</h3>
      <ul class="entry">
        
          <li class='link'><a href='http://www.cnblogs.com/jietang/' target="_blank">唐洁的博客</a></li>
        
          <li class='link'><a href='http://rednaxelafx.iteye.com/' target="_blank">R大的博客</a></li>
        
          <li class='link'><a href='http://www.hollischuang.com/' target="_blank">阿里大神的博客</a></li>
        
          <li class='link'><a href='http://blog.csdn.net/IT_faquir/' target="_blank">IT_faquir的专栏</a></li>
        
      </ul>
  </div>


  
  <div class="widget tag">
    <h3 class="title">思维导图</h3>
      <ul class="entry">
        
          <li class='link'><a href='https://fengbo4213.github.io/img/开源协议.png' target="_blank">开源协议简介</a></li>
        
          <li class='link'><a href='https://www.processon.com/diagraming/5b0cf757e4b009aef58d4b9d' target="_blank">我的知识体系</a></li>
        
          <li class='link'><a href='https://www.processon.com/view/link/5a2a00e5e4b015e677290b4f' target="_blank">简单的网站架构</a></li>
        
      </ul>
  </div>


  
  <div class="widget tag">
    <h3 class="title">在线手册</h3>
      <ul class="entry">
        
          <li class='link'><a href='http://v3.bootcss.com/' target="_blank">BootStrap官方手册</a></li>
        
          <li class='link'><a href='http://www.iconfont.cn/http://element.eleme.io/#/zh-CN/' target="_blank">阿里巴巴矢量图标库</a></li>
        
      </ul>
  </div>


  
<div class="widget tag">
  <h3 class="title">最新文章</h3>
  <ul class="entry">
    
      <li>
        <a href="/2123/08/30/基础之MySQL原理/">MySQL原理</a>
      </li>
    
      <li>
        <a href="/2024/01/01/其它之ClickHouse索引/">ClickHouse索引</a>
      </li>
    
      <li>
        <a href="/2023/12/17/其它之MySQL线程池/">MySQL线程池</a>
      </li>
    
      <li>
        <a href="/2023/12/16/其它之InnoDB性能优化基础/">InnoDB性能优化基础</a>
      </li>
    
      <li>
        <a href="/2023/12/03/其它之Java8之后的版本新特性/">Java8之后的版本新特性</a>
      </li>
    
  </ul>
</div>

</aside>
    <div class="clearfix"></div>
  </div>
  <footer id="footer" class="inner"><div class="alignleft">
  
  &copy; 2024 fengbo
  
</div>
<div class="clearfix"></div></footer>
  <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>



</body>
</html>

